﻿using Mapster;
using MyCompany.MyProject.Common;
using MyCompany.MyProject.Common.Core;
using MyCompany.MyProject.Model;
using MyCompany.MyProject.Model.Logs;
using MyCompany.MyProject.Serilog.Extensions;
using Serilog.Events;
using Serilog.Sinks.PeriodicBatching;
using SqlSugar;

namespace MyCompany.MyProject.Serilog.Sink;

public class LogBatchingSink : IBatchedLogEventSink
{
    public async Task EmitBatchAsync(IEnumerable<LogEvent> batch)
    {
        var sugar = App.GetService<ISqlSugarClient>(false);
        
        await WriteLogs(sugar, batch.FilterRemoveOtherLog());
        //await WriteTLog<AuditSqlLog>(sugar, batch.FilterSqlLog());
        await WriteSqlLog(sugar, batch.FilterSqlLog());
    }

    public Task OnEmptyBatchAsync()
    {
        return Task.CompletedTask;
    }

    #region Write To

    private async Task WriteLogs(ISqlSugarClient db ,IEnumerable<LogEvent> batch)
    {
        if(!batch.Any()) return;
        var group = batch.GroupBy(s => s.Level);
        foreach( var item in group)
        {
            switch (item.Key)
            {
                //case LogEventLevel.Information: await WriteTLog<GlobalInformationLog>(db, item); break;
                //case LogEventLevel.Warning: await WriteTLog<GlobalWarningLog>(db, item); break;
                //case LogEventLevel.Error:
                //case LogEventLevel.Fatal: await WriteTLog<GlobalErrorLog>(db, item); break;
                
                case LogEventLevel.Information:await WriteInformationLog(db, item); break;
                case LogEventLevel.Warning: await WriteWarningLog(db, item); break;
                case LogEventLevel.Error:
                case LogEventLevel.Fatal: await WriteErrorLog(db, item); break;
            }
        }
    }

    private async Task WriteTLog<T>(ISqlSugarClient db, IEnumerable<LogEvent> batch) where T : BaseLog
    {
        if (!batch.Any()) return;
        var logs = new List<T>();
        foreach (var logEvent in batch)
        {
            var log = logEvent.Adapt<T>();
            log.Message = logEvent.RenderMessage();
            log.Properties = logEvent.Properties.ToJson();
            log.DateTime = logEvent.Timestamp.DateTime;
            logs.Add(log);
        }
        await db.AsTenant().InsertableWithAttr(logs).SplitTable().ExecuteReturnSnowflakeIdAsync();
    }


    public async Task WriteSqlLog(ISqlSugarClient db,IEnumerable<LogEvent> batch)
    {
        if (!batch.Any()) return;
        var logs = new List<AuditSqlLog>();
        foreach (var logEvent in batch)
        {
            var log = logEvent.Adapt<AuditSqlLog>();
            log.Message = logEvent.RenderMessage();
            log.Properties = logEvent.Properties.ToJson();
            log.DateTime = logEvent.Timestamp.DateTime;
            logs.Add(log);
        }

        await db.AsTenant().InsertableWithAttr(logs).SplitTable().ExecuteReturnSnowflakeIdAsync();
    }

    public async Task WriteInformationLog(ISqlSugarClient db, IEnumerable<LogEvent> batch)
    {
        if (!batch.Any()) return;
        var logs = new List<GlobalInformationLog>();
        foreach (var logEvent in batch)
        {
            var log = logEvent.Adapt<GlobalInformationLog>();
            log.Message = logEvent.RenderMessage();
            log.Properties = logEvent.Properties.ToJson();
            log.DateTime = logEvent.Timestamp.DateTime;
            logs.Add(log);
        }

        await db.AsTenant().InsertableWithAttr(logs).SplitTable().ExecuteReturnSnowflakeIdAsync();
    }

    public async Task WriteWarningLog(ISqlSugarClient db, IEnumerable<LogEvent> batch)
    {
        if (!batch.Any()) return;
        var logs = new List<GlobalWarningLog>();
        foreach (var logEvent in batch)
        {
            var log = logEvent.Adapt<GlobalWarningLog>();
            log.Message = logEvent.RenderMessage();
            log.Properties = logEvent.Properties.ToJson();
            log.DateTime = logEvent.Timestamp.DateTime;
            logs.Add(log);
        }

        await db.AsTenant().InsertableWithAttr(logs).SplitTable().ExecuteReturnSnowflakeIdAsync();
    }

    public async Task WriteErrorLog(ISqlSugarClient db, IEnumerable<LogEvent> batch)
    {
        if (!batch.Any()) return;
        var logs = new List<GlobalErrorLog>();
        foreach (var logEvent in batch)
        {
            var log = logEvent.Adapt<GlobalErrorLog>();
            log.Message = logEvent.RenderMessage();
            log.Properties = logEvent.Properties.ToJson();
            log.DateTime = logEvent.Timestamp.DateTime;
            logs.Add(log);
        }

        await db.AsTenant().InsertableWithAttr(logs).SplitTable().ExecuteReturnSnowflakeIdAsync();
    }
    #endregion
}
